Skip to content

Add find_token MCP tool support#3

Merged
RaghavSood merged 5 commits intofeature/mcp-vault-infofrom
feature/find-token-support
Feb 24, 2026
Merged

Add find_token MCP tool support#3
RaghavSood merged 5 commits intofeature/mcp-vault-infofrom
feature/find-token-support

Conversation

@RaghavSood
Copy link
Collaborator

Summary

  • Adds structured passthrough for the find_token MCP tool so frontend apps receive token/chain data they can act on
  • Adds TokenSearchResult, Token, and TokenDeployment types mirroring the MCP tool response
  • Adds tokens field to SendMessageResponse (omitted when nil)
  • Parses find_token results in trackToolResult alongside existing transaction/suggestion extraction

Stacked on #2.

Frontend Integration

When the AI calls find_token, the API response will include a new tokens field with the full token data (name, symbol, logo, market cap rank, and per-chain deployments with contract addresses and decimals). Frontend apps should use this to present an "Add Token" flow, letting the user select which chain deployments to add to their vault.

See the PR description below for the full response schema and integration guide.


tokens field schema

// Only present when find_token was called and returned results
"tokens": {
  "tokens": [
    {
      "id": "usd-coin",              // CoinGecko ID
      "name": "USD Coin",
      "symbol": "USDC",
      "market_cap_rank": 7,           // 0 = unranked
      "logo": "https://assets.coingecko.com/coins/images/6319/large/usdc.png",
      "deployments": [
        {
          "chain": "Ethereum",        // Matches Vultisig chain names
          "contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
          "decimals": 6
        }
      ]
    }
  ]
}

Example full response

{
  "message": { "role": "assistant", "content": "I found USDC. It's available on several chains..." },
  "tokens": {
    "tokens": [
      {
        "id": "usd-coin",
        "name": "USD Coin",
        "symbol": "USDC",
        "market_cap_rank": 7,
        "logo": "https://assets.coingecko.com/coins/images/6319/large/usdc.png",
        "deployments": [
          { "chain": "Ethereum", "contract_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "decimals": 6 },
          { "chain": "Arbitrum", "contract_address": "0xaf88d065e77c8cc2239327c5edb3a432268e5831", "decimals": 6 },
          { "chain": "Polygon", "contract_address": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359", "decimals": 6 }
        ]
      }
    ]
  }
}

Test plan

  • Verify tokens field is omitted from response JSON when find_token is not called
  • Verify tokens field is populated when find_token returns results
  • Verify multiple tokens are returned when the query matches more than one (e.g. "USDC")
  • Verify tokens field is omitted when find_token returns an error
  • Build passes: go build ./...

🤖 Generated with Claude Code

RaghavSood and others added 2 commits February 24, 2026 12:30
Extract token search results from the find_token MCP tool and pass them
as structured data in the API response so frontend apps can prompt users
to add tokens/chains to their vault.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two issues prevented the tokens field from appearing in API responses:

1. CallTool discarded text on IsError — when the MCP tool set IsError: true,
   CallTool returned a Go error and the text content was lost. Now returns
   a ToolError that carries the text, so executeTool can still pass it to
   trackToolResult for structured extraction.

2. trackToolResult assumed pure JSON — MCP tools may return multiple text
   content blocks (joined with \n) or mix descriptive text with JSON. The
   direct json.Unmarshal failed silently. Now uses extractTokens() which
   tries direct unmarshal first, then scans for JSON objects in the text
   using json.Decoder (which handles trailing content).

Also adds diagnostic logging when parsing fails so we can see the actual
MCP result text in logs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@RaghavSood RaghavSood force-pushed the feature/find-token-support branch from 3de125d to 5078c33 Compare February 24, 2026 04:31
RaghavSood and others added 3 commits February 24, 2026 12:48
Integrate MCP resources protocol (resources/list, resources/read) to
discover and load skill guides from the MCP server. Skills are markdown
documents at skills/{slug}.md that provide detailed workflow instructions.

The skill list is injected into the system prompt so the LLM knows what's
available, but skill content is only loaded on-demand via the new get_skill
tool when relevant to the user's request. This keeps the context window
lean as the skill library grows.

- MCP client: add ListSkills, ReadSkill, SkillSummary with TTL caching
- Agent: extend MCPToolProvider interface with skill methods
- Agent: inject skill summary into system prompt after tool descriptions
- Tools: add get_skill native tool (only registered when skills exist)
- Executor: add get_skill handler delegating to MCP ReadSkill
- Main: pre-warm skill cache at startup alongside tools

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The MCP server returns skill resources with URIs like
"skill://vultisig/evm-contract-call.md" but extractSkillSlug was
filtering for the "skills/" prefix, discarding all entries.

- extractSkillSlug now extracts the last path segment before .md,
  handling any URI scheme (skill://, skills/, etc.)
- ReadSkill now looks up the full URI from the skill cache instead
  of constructing it, so it works with any URI format

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add MCP skill discovery and on-demand loading
@RaghavSood RaghavSood merged commit 0ee21c3 into feature/mcp-vault-info Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant